var createError = require('http-errors'); // 创建错误的模板
var express = require('express');
var fsPromise = require('fs/promises')  //用来使用它里面的删除文件的方法
var path = require('path');  // 路径模块
var cookieParser = require('cookie-parser');  // 解析cookie文件 （用于登录功能）
var lessMiddleware = require('less-middleware'); // 解析 less文件
var logger = require('morgan'); // log文件记录的中间件

// 引入session 文件 
const session = require('express-session')
// 为了将session数据保存在MongoDB数据库中，还要安装一个三方的模块(connect-mongo) 并引入
const MongoStore = require('connect-mongo')(session)  //连接数据库
const formidableMiddleware = require('express-formidable')  //解析表单中的文件和字段
// 引入flash 用来 设置 提示信息
const flash = require('connect-flash')

// 引入 config 配置文件
const config = require('./config')
const routes = require('./routes');

var app = express();

// view engine setup  //设置模板引擎
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

app.use(logger('dev'));  //网站log
app.use(express.json());  //JSON 
// app.use(express.urlencoded({ extended: false }));  //解析post，从req.body中拿数据  这个会与express-formidable中间件起冲突，只能选其一

app.use(cookieParser());  //解析cookie的中间件
app.use(lessMiddleware(path.join(__dirname, 'public'))); //用来解析less的中间件  把less文件解析成 css文件
app.use(express.static(path.join(__dirname, 'public'))); //静态资源文件
app.use(formidableMiddleware({   //需要引入：express-formidable
  encoding: 'utf-8',//编码格式
  uploadDir: path.join(__dirname, 'public/upload'),//设定文件上传路径
  multiples: 'true',//允许多个文件上传
  keepExtensions: true  //保留上传文件的后缀名

}, [{
  event: 'file',
  action: function (req, res, next, name, file) {
    // console.log(name, file);
    // console.log('file事件被触发');
    if (file && file.size === 0) {
      // console.log('name:', name, '    value:', value);
      // 删除文件  fs.unlink()  需要引入fs模块
      fsPromise.unlink(file.path).then().catch(err => console.log(next(err)))
    }
  }
}]))
// 设置 后端的session中间件 （为了使用session）
app.use(session({
  name: config.db.name,// 设置 cookie 中保存 session id 的字段名称
  secret: config.session.secret,// 通过设置secret 来计算 hash 值 并存放在 cookie 中，使产生的 signedCookie 防篡改
  resave: false,//强制更新 session
  saveUninitialized: false, // 设置为false  强制将未初始化的session进行存储。当新建了一个session且未设定属性或值时，它就处于未初始化状态。默认：true，建议设置为false。以减轻服务端存储压力。
  cookie: {
    maxAge: config.session.maxAge, //过期时间(单位：毫秒)，过期后 cookie 中的 session id 自动删除  
  },
  store: new MongoStore({ // 将 session 存储到 MongoDB
    url: `${config.db.url}/${config.db.key}` // MongoDB的url和存储的数据库  
  })

}))
// 使用flash
app.use(flash())

// 所有模板都可以访问到locals中的数据，相当于网站的全局变量
app.locals.title = config.site.title
app.locals.site = { name: config.site.name, }
// 设置全局参数
app.use((req, res, next) => {
  // 解决两个中间件起冲突的问题 : 使用扩展运算符把req.body和req.fields中的数据合并到一个新的数组中
  req.body = { ...req.body, ...req.fields }

  // authUser: 认证用户
  res.locals.authUser = req.session.user  //req.session.user 只有在登陆成功之后才会在session里面添加user

  // flash只写一个参数代表从flash 存储中读取数据 并把这条数据从session中删除
  res.locals.alertSuccess = req.flash('success')
  res.locals.alertError = req.flash('error')
  next()
})

routes(app)
// catch 404 and forward to error handler
app.use(function (req, res, next) {
  next(createError(404));
});

// error handler //集中处理错误中间件
app.use(function (err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;
